/* Copyright (c) 2007-2008, Jeffrey R Griffin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Jeffrey R Griffin nor the
*       names of his contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Jeffrey R Griffin ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package net.visibleblue.android.serialintents;

import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentReceiver;
import android.content.PackageManager;
import android.content.DialogInterface.OnClickListener;
import android.content.PackageManager.ResolveInfo;
import android.content.Resources.Theme;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Window;

public class NotificationActivity extends Activity {

	private class CallbackReceiver extends IntentReceiver
	{
		@Override
		public void onReceiveIntent(Context context, Intent intent) {
			_progress.cancel();
			((NotificationActivity)context).finish();
		}
	}

	private class FinishClick implements OnClickListener
	{	
		@Override
		public void onClick(DialogInterface arg0, int arg1) {
			NotificationActivity.this.finish();
		}
	}

	private Intent _info = null;
	private Bundle _icicle = null;
	private ProgressDialog _progress = null;
	private CharSequence _intentReceiverName = null;
	private ResolveInfo _resolved = null;

	private class ActivityClick implements OnClickListener
	{	
		@Override
		public void onClick(DialogInterface arg0, int arg1) {
			
			//for some reason startActivity has trouble resolving the activity, even 
			//though we already did it.  Let's help it out.
			_info.setClassName(_resolved.activityInfo.applicationInfo.packageName, 
					_resolved.activityInfo.className);
			startActivity(_info.addLaunchFlags(Intent.NEW_TASK_LAUNCH).
					addLaunchFlags(Intent.MULTIPLE_TASK_LAUNCH));
			finish();
		}
	}

	private class ServiceClick implements OnClickListener
	{	
		@Override
		public void onClick(DialogInterface arg0, int arg1) {
			startService(_info.addLaunchFlags(Intent.NEW_TASK_LAUNCH), _icicle);
		}
	}

	private class IntentReceiverClick implements OnClickListener
	{	
		@Override
		public void onClick(DialogInterface arg0, int arg1) {
			CallbackReceiver resultReceiver = new CallbackReceiver();
			broadcastIntent(_info, null, resultReceiver, null, Activity.RESULT_OK,
					null, null);
			_progress = ProgressDialog.show(NotificationActivity.this, "Running... ", 
					_intentReceiverName, true, false);
		}
	}
	
	//this is needed due to a bug where the dialog will get swapped with the activity in the
	//z order
	private Handler _dialogHandler = new Handler()
	{
		@Override
		public void handleMessage(Message msg)
		{
			if(_info!=null)
			{
				//we can use the PackageManager to determine what sort of task can fulfill
				//our intent, enabling us to launch more than just an activity from a 
				//notification
				PackageManager pm = getPackageManager();
				List<ResolveInfo> resolved = pm.queryIntentReceivers(_info, 0);
				StringBuilder builder = new StringBuilder("Run ");
				if(resolved==null || resolved.size()==0)
				{
					resolved = pm.queryIntentActivities(_info, 0);
					if(resolved==null || resolved.size()==0)
					{
						resolved = pm.queryIntentServices(_info, 0);
						if(resolved==null || resolved.size()==0)
						{
							AlertDialog.show(NotificationActivity.this, null, 
									"Intent could not be resolved.", 
									"OK", new FinishClick(), false, null);
						}
						else
						{
							_resolved = resolved.get(0);
							builder.append(getResolvedName(_resolved, pm));
							builder.append('?');
							AlertDialog.show(NotificationActivity.this, 
									builder, 
									(CharSequence)_info.getExtra(SerialIntents.DESCRIPTION_KEY), 
									"Yes", new ServiceClick(), "No", new FinishClick(), 
									false, null);
						}
					}
					else
					{
						_resolved = resolved.get(0);
						builder.append(getResolvedName(_resolved, pm));
						builder.append('?');
						AlertDialog.show(NotificationActivity.this, 
								builder, 
								(CharSequence)_info.getExtra(SerialIntents.DESCRIPTION_KEY), 
								"Yes", new ActivityClick(), "No", 
								new FinishClick(), false, null);
					}
				}
				else
				{
					_resolved = resolved.get(0);
					_intentReceiverName = getResolvedName(_resolved, pm);
					builder.append(_intentReceiverName);
					builder.append('?');
					AlertDialog.show(NotificationActivity.this, 
							builder, 
							(CharSequence)_info.getExtra(SerialIntents.DESCRIPTION_KEY), 
							"Yes", new IntentReceiverClick(), 
							"No", new FinishClick(), false, null);
				}
			}
			else
			{
				AlertDialog.show(NotificationActivity.this, "Barcode detected.", 
						(CharSequence)_info.getExtra(SerialIntents.DESCRIPTION_KEY), 
						"OK", new FinishClick(), null, null, false, null);
			}

		}
	};
	
	private static CharSequence getResolvedName(ResolveInfo resolved, PackageManager pakMan)
	{
		CharSequence label = pakMan.getResolveLabel(resolved);
		if(label==null && resolved.activityInfo!=null)
		{
			int index = Math.max(resolved.activityInfo.className.lastIndexOf("."), 
					resolved.activityInfo.className.lastIndexOf("$"));
			label = resolved.activityInfo.className.substring(index+1);
		}
		if(label==null && resolved.serviceInfo!=null)
		{
			int index = Math.max(resolved.serviceInfo.className.lastIndexOf("."), 
					resolved.serviceInfo.className.lastIndexOf("$"));
			label = resolved.serviceInfo.className.substring(index+1);
		}
		return label;
	}

	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		setContentView(R.layout.main);
		_info = (Intent)getIntent().getExtra(SerialIntents.RUN_INTENT);
		//_info = SerialIntents.getIntentInfo(getIntent().getExtras());
		_icicle = icicle;
		_dialogHandler.sendMessage(new Message());
	} 

	@Override
	public void finish() {
		SerialIntents.finishNotification(
				getIntent().getExtras().getInteger(SerialIntents.NOTIFICATION_ID));
		super.finish();
	}

	@Override
	protected void applyThemeResource(Theme theme, int resid, boolean first) {
		//it seems strange that I am un-setting my style and resetting the aspects of it,
		//but both are necessary.  The initial style so that we don't have a strange UI flicker
		//before we get to this point, and this code so that we have an invisible title bar
		//on the activity window, but not the alert dialogs.
		theme.applyStyle(android.R.style.Theme_Dark, true);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setBackgroundDrawable(getResources().getDrawable(R.drawable.transparent));
		//super.applyThemeResource(theme, resid, first);
	}
}
